package com.rtmanager.data;

import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.util.regex.Pattern;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.impl.client.BasicResponseHandler; 
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;

import android.util.Log;
import com.rtmanager.exceptions.*;

/**
 * Classe chargée de la communication avec le serveur
 * @author fab
 *
 */
public class RTCommunicator {
	/**
	 * url du serveur rt
	 */
	private String server_url;
	/**
	 * login de l'utilisateur
	 */
	private String login;
	/**
	 * mot de passe de l'utilisateur
	 */
	private String password;
	/**
	 * dernière reponse du serveur (au format texte)
	 */
	private String lastTxtResponse="";

	private Ticket[] listTicket=null;
	
	/**
	 * Type pour les parametre dans les requetes
	 * @author fab
	 *
	 */
	private class Parameter {
		public String param;
		public String value;
		
		public Parameter(String param,String value) {
			this.param=param;
			this.value=value;
		}
		
		/** 
		 * permet d'obtenir les valeurs avec l'encodage url
		 * @return
		 */
		public String getValueURLEncode() {
			return URLEncoder.encode(this.value);
		}
		
		public String toStringURLEncode() {
			return param + "=" + this.getValueURLEncode();
		}
	}
	
	/**
	 * 
	 * @param server_url : url du serveur (sans la partie REST)
	 * @param login : login de l'utilisateur
	 * @param password : mot de passe utilisateur
	 */
	public RTCommunicator(String server_url, String login, String password) {
		this.server_url=server_url;
		this.login = login;
		this.password = password;
	}
	
	
	/**
	 * methode généraliste pour interroger le serveur
	 * @param query : requete au format REST 
	 * {@link http://wiki.bestpractical.com/view/REST}
	 * @return retourne la réponse en brut du serveur
	 * @throws Exception 
	 */
	private String sendQuery(String strRequest) throws Exception {
		String result="";
		try {
			HttpClient httpclient = new DefaultHttpClient();
			Parameter param_user = new Parameter("user",this.login);
			Parameter param_pass = new Parameter("pass",this.password); 
			
			HttpPost request = new HttpPost(
					this.getBaseURI()
					+ strRequest 
					+ "&" + param_user.toStringURLEncode() 
					+ "&" + param_pass.toStringURLEncode()
			);	
			
			ResponseHandler<String> handler = new BasicResponseHandler();  

			result = httpclient.execute(request, handler);
			httpclient.getConnectionManager().shutdown();
			lastTxtResponse = result;
			return result;
		} 
		catch (Exception e) {  
			e.printStackTrace();
			return "";
		}  

		
		
	}
	
	
	/**
	 * méthode pour obtenir l'url du serveur
	 * @return url du serveur
	 */
	public String getServer() {
		return this.server_url;
	}
	
	/**
	 * renvoi le dernier resultat (code) du serveur
	 * @return
	 */
	public int getLastResultCode() {
		String[] lines = lastTxtResponse.split("\n");
		int result = 0;
		if (lines.length > 0  ) {
			if ( Pattern.matches("^RT/[0-9.]+ [0-9]+ .*", lines[0]) ) {
				return new Integer(lines[0].split(" ")[1]);
			}
		}
		
		return result;
		//return 200;
	}
	
	private String getLastResultStr() {
		return this.lastTxtResponse;
	}
	
	public Ticket getTicketInfos(int TicketId) throws Exception {
		return new Ticket(this.sendQuery("/ticket/"+TicketId+"?"));
	}

	
	/**
	 * recherche dans les tickets
	 * @param search : requete au format REST
	 * @return renvoie la réponse en brut
	 * @throws Exception 
	 */
	private String search(Parameter[] params) throws Exception {
		String strRequest = "";
		
		/* construction de la requete */
		for ( int i=0; i<params.length;i++ ) {
			strRequest += params[i].toStringURLEncode()+"&";
		}
		return this.sendQuery("/search/ticket?"+strRequest);
	}
	
	
	/**
	 * recupère l'historique du ticket
	 * 
	 */
	private TicketHistoryEntry[] getTicketHistory(int ticketId) {
		TicketHistoryEntry[] ticketHistory=null;
		try {
			String strHistory = this.sendQuery("/ticket/"+ticketId+"/history/?format=l");
			String[] arrayStrHistory = strHistory.split("\n");
			ticketHistory=new TicketHistoryEntry[arrayStrHistory.length];
			
			for(int i=0 ; i < arrayStrHistory.length ; i++ ) {
				ticketHistory[i] = new TicketHistoryEntry(arrayStrHistory[i]);
			}
			
		} 
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return ticketHistory;
	}
	
	/**
	 * Test la connectivité avec le serveur
	 * @return true si le serveur répond
	 * @throws Exception 
	 */
	public String testServer() throws Exception {
		
		try {
			String result=this.sendQuery("/ticket/1?");
			return result;
		}
		catch (Exception e) {  
			e.printStackTrace();
			return "";
		}  		
	}
	
	
	
	/**
	 * renvoie les tickets ouverts de l'utilisateur
	 * @return
	 * @throws Exception 
	 */
	public Ticket[] getOwnerOpen() throws RTConnectionException {
		String TAG = this.getClass().getCanonicalName() + ":getOwnerOpen";
		try {
			String strResult = this.search(
					new Parameter[] {
							new Parameter("query","owner='"+this.login+"' AND status = 'open'"),
							new Parameter("format","l")
						}
					);
			Log.d(TAG, "strResult : " + strResult);
		
			String[] strListTickets = strResult.split("--");
		
			listTicket=new Ticket[strListTickets.length];
			Log.d(">>>>>>>>>COMPTAGE : ","Tickets : " + strListTickets.length);
			for ( int i=0 ; i< strListTickets.length ; i++ ) {
				listTicket[i] = new Ticket(strListTickets[i]);
				/* enregistrement de l'historique */
				listTicket[i].setHistory(this.getTicketHistory(listTicket[i].getId()));
				Log.d(">>>> TICKET : ","TicketId : [" + i + "] " + listTicket[i].getId());
			}
			Log.d(TAG,"TicketId : [" + listTicket.length);
			

	 		
		}
		catch(UnknownHostException e) {
			throw new RTConnectionException();
		}
	 	catch(Exception e) {
	 		e.printStackTrace();
	 	}
		return listTicket;
	}
	
	
	
	/**
	 * renvoie les tickets ouverts de l'utilisateur
	 * @return
	 * @throws Exception 
	 */
	public String getOwnerStalled() throws Exception {
		String strResult = this.search(
				new Parameter[] {
						new Parameter("query","owner='"+this.login+"' AND status = 'stalled'")
					}
				);
		return strResult;
		
	}	
	
	/**
	 * renvoie l'url de base pour attaquer le serveur au format REST
	 * @return l'url de base
	 */
	private String getBaseURI() {
		return this.server_url + "/REST/1.0";
	}
	
	public String toString() {
		
		try {
			return "login :" + this.login + "\n" + "pass :" + this.password + "\n" + "server_url : " + this.server_url + "\n" + "number Open tickets : " + getOwnerOpen()[getOwnerOpen().length-1].toString() + "\n" + this.lastTxtResponse;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return e.getMessage();
		}
		
	}
	
}
